package bibbletex.helpers;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.util.ArrayList;
import java.util.List;

import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;

public class HTMLParser extends DefaultHandler {

	/** Character Data innerhalb des aktuellen Tags. */
	private StringBuffer stringBuffer = null;
	private String site = "";
	private List<List<String>> results;

	public HTMLParser(String path) {
		results = new ArrayList<List<String>>();
		// currentItem wird in startElement initialisiert
		stringBuffer = new StringBuffer();
		try {
			// Neuen SAX-Parser erzeugen
			SAXParserFactory factory = SAXParserFactory.newInstance();

			factory.setValidating(false);
			factory.setNamespaceAware(true);
			factory.setFeature(
					"http://apache.org/xml/features/nonvalidating/load-external-dtd",
					false);

			// Parser erzeugen
			SAXParser saxParser = factory.newSAXParser();

			// XML einlesen
			URL website = new URL(path);
			BufferedReader in = new BufferedReader(new InputStreamReader(
					website.openStream()));

			String site = "";
			String inputLine;

			while ((inputLine = in.readLine()) != null)
				site += inputLine + "\n";

			in.close();

			// linebreaks ändern -> unnötig
			// site = site.replace("\r\n","\n");

			// & Paramater - Fehler umgehen
			// könnte mit anderen Entitäten in Konflikt stehen: &auml; ->
			// &amp;auml;
			site = site.replace("&", "&amp;");

			// nicht deklarierte Entitäten durch numerische Referenz ersetzen
			// & -> &amp; - Korrektur berichtigen ;)
			site = site.replace("&amp;auml;", "&#228;");
			site = site.replace("&amp;ouml;", "&#246;");
			site = site.replace("&amp;uuml;", "&#252;");
			site = site.replace("&amp;szlig;", "&#223;");
			site = site.replace("&amp;Auml;", "&#196;");
			site = site.replace("&amp;Ouml;", "&#214;");
			site = site.replace("&amp;Uuml;", "&#220;");
			site = site.replace("&amp;nbsp;", "&#160;");
			site = site.replace("selected", "");

			InputStream instream = new ByteArrayInputStream(site.getBytes());

			// Codierungsprobleme umgehen [UTF-8]
			InputSource source = new InputSource(
					prepareInputStreamReader(instream));

			// vorbereitete Version parsen
			// XML Datei parsen, die entsprechenden Methoden des DefaultHandler
			// werden als Callback aufgerufen.

			// System.out.println("Parsing " + path);
			saxParser.parse(source, this);

		} catch (Exception e) {
			System.out.println(e);
			e.printStackTrace();
		}
	}

	// ungültige Zeichen durch "?" ersetzen
	private Reader prepareInputStreamReader(InputStream inputStream) {
		// Strip all invalid UTF-8 sequences from input
		CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
		decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
		decoder.onMalformedInput(CodingErrorAction.REPLACE);
		decoder.replaceWith("?");

		return new InputStreamReader(inputStream, decoder);
	}

	boolean open = false;
	boolean result = false;
	int count = 0;
	String pointer = "nope";
	ArrayList<String> urls = new ArrayList<String>();
	ArrayList<StringBuilder> title = new ArrayList<StringBuilder>();
	ArrayList<StringBuilder> infos = new ArrayList<StringBuilder>();
	ArrayList<StringBuilder> abstractContent = new ArrayList<StringBuilder>();
	int counter = -1;
	boolean singleWhiteSpace = true;

	// Behandlung der Start-Tags
	public void startElement(String namespaceURI, String localName,
			String qName, Attributes atts) throws SAXException {
		if (count > 0) {
			count++;
		}
		if (result) {
			if (qName.equals("a")) {
				for (int i = 0; i < atts.getLength(); i++) {
					if (atts.getQName(i).equals("class")
							&& atts.getValue(i).equals("remove doc_details")) {
						urls.add(atts.getValue(atts.getIndex("href")));
						pointer = "title";
						counter++;
						title.add(new StringBuilder());
					}
				}
			}
		
			if (qName.equals("div")) {
				for (int i = 0; i < atts.getLength(); i++) {
					if (atts.getQName(i).equals("class")
							&& atts.getValue(i).equals("pubinfo")) {
						pointer = "info";
						infos.add(new StringBuilder());
					}
					else if(atts.getQName(i).equals("class")
							&& atts.getValue(i).equals("pubabstract")){
						pointer = "abstract";
						abstractContent.add(new StringBuilder());
					}
				}
			}
		}
		if (qName.equals("div")) {
			for (int i = 0; i < atts.getLength(); i++) {
				if (atts.getQName(i).equals("class")
						&& atts.getValue(i).equals("result")) {
					result = true;
					count = 1;
				}
			}

		}
		open = true;
		stringBuffer.setLength(0);
	}

	// Behandlung der End-Tags
	public void endElement(String namespaceURI, String localName, String qName) {
		if (count == 1) {
			result = false;
			count--;
		} else if (count > 1) {
			count--;
		}
		open = false;
		if(qName.equals("div")||qName.equals("h3")){
			pointer = "nope";
		}
	}

	// Behandlung des Inhalts zwischen den Tags
	public void characters(char ch[], int start, int length) {
		if (result) {

			
			if(pointer.equals("title")){
				for (int i = start; i < start + length; i++) {
					if(ch[i] == ' ' && singleWhiteSpace){
						title.get(counter).append(ch[i]);
						singleWhiteSpace = false;
					}
					if(ch[i] != ' '){
						title.get(counter).append(ch[i]);
						singleWhiteSpace = true;
					}
				}
			} else if(pointer.equals("info")){
				for (int i = start; i < start + length; i++) {
					if(ch[i] == ' ' && singleWhiteSpace){
						infos.get(counter).append(ch[i]);
						singleWhiteSpace = false;
					}
					if(ch[i] != ' '){
						infos.get(counter).append(ch[i]);
						singleWhiteSpace = true;
					}
				}
			} else if(pointer.equals("abstract")){
				for (int i = start; i < start + length; i++) {
					if(ch[i] == ' ' && singleWhiteSpace){
						abstractContent.get(counter).append(ch[i]);
						singleWhiteSpace = false;
					}
					if(ch[i] != ' '){
						abstractContent.get(counter).append(ch[i]);
						singleWhiteSpace = true;
					}
					
				}
			}
			
			
			
			

		}
	}
	
	public void endDocument(){
		for(int i = 0; i < title.size(); i++){
			String site = new String();
			String url = new String("http://citeseerx.ist.psu.edu"+urls.get(i));
			site = "<div class=\"searchresult\"><h3><a href =\"" + url + "\" target=\"_blank\"  >";
			site = site + title.get(i).toString().replace("\n", "") + "</a></h3>";
			site = site + "<div class=\"importDetails\">"  +infos.get(i).toString().replace("\n", "") + "</div>";
			site = site + "<div class=\"importDescription\">" + abstractContent.get(i).toString().replace("\n", "") + "</div></div>";
			List<String> result = new ArrayList<String>();
			result.add(url);
			result.add(site);
			results.add(result);
		}
	}

	public List<List<String>> getResults() {
		return this.results;
	}
}
